package com.sun.lib.base.basemvp;


import com.orhanobut.logger.Logger;
import com.sun.lib.net.DataManager;
import com.sun.lib.rx.Disposables;

import org.json.JSONException;
import org.json.JSONObject;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

/**
 * Created by sunxiquan on 2018/9/27.
 * <p>
 * #                                                   #
 * #                       _oo0oo_                     #
 * #                      o8888888o                    #
 * #                      88" . "88                    #
 * #                      (| -_- |)                    #
 * #                      0\  =  /0                    #
 * #                    ___/`---'\___                  #
 * #                  .' \\|     |# '.                 #
 * #                 / \\|||  :  |||# \                #
 * #                / _||||| -:- |||||- \              #
 * #               |   | \\\  -  #/ |   |              #
 * #               | \_|  ''\---/''  |_/ |             #
 * #               \  .-\__  '-'  ___/-. /             #
 * #             ___'. .'  /--.--\  `. .'___           #
 * #          ."" '<  `.___\_<|>_/___.' >' "".         #
 * #         | | :  `- \`.;`\ _ /`;.`/ - ` : | |       #
 * #         \  \ `_.   \_ __\ /__ _/   .-` /  /       #
 * #     =====`-.____`.___ \_____/___.-`___.-'=====    #
 * #                       `=---='                     #
 * #     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~   #
 * #                                                   #
 * #               佛祖保佑         永无BUG              #
 * #                                                   #
 */
public abstract class BasePresenter<T extends MvpView, K extends IModel> implements Presenter {
    private static final String STATUS = "status";
    private static final String DATA = "data";
    private static final String CODE = "code";

    private K mModel;
    private WeakViewReference<MvpView> weakReference;
    public final DataManager dataManager;

    public BasePresenter() {
        this.dataManager = DataManager.getInstance();
    }

    @Override
    public void attachView(MvpView view) {
        weakReference = new WeakViewReference<>(view);
        initModel();
    }

    // 使用反射方式创建model
    private void initModel() {
        ParameterizedType type = (ParameterizedType) this.getClass().getGenericSuperclass();
        if (type != null) {
            Type[] types = type.getActualTypeArguments();
            try {
                mModel = (K) ((Class<?>) types[1]).newInstance();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InstantiationException e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public void detachView() {
        getModel().dispose();
        weakReference = null;
    }

    public WeakViewReference<T> getMvpView() {
        return (WeakViewReference<T>) weakReference;
    }

    public boolean isViewAttached() {
        Logger.d("hashcode:" + hashCode());
        return weakReference != null;
    }

    public void checkViewAttached() {
        if (!isViewAttached()) {
            throw new MvpViewNotAttachedExcepition();
        }

    }

    protected K getModel() {
        return mModel;
    }

    public static class MvpViewNotAttachedExcepition extends RuntimeException {
        public MvpViewNotAttachedExcepition() {
            super("please call Presenter.attachView(MvpView) before requesting data to the presenter");
        }
    }

    protected boolean isDataValid(String json) {

        String status = "1";
        String code = "1";
        try {
            JSONObject jsonObj = new JSONObject(json);
            if (jsonObj.has(STATUS)) {
                status = jsonObj.getString(STATUS);
                JSONObject data = jsonObj.getJSONObject(DATA);
                if (data != null && data.has(CODE)) {
                    code = data.getString(CODE);
                }

            }
        } catch (JSONException e) {
            e.printStackTrace();
        } finally {
            if (status.equals("1") && code.equals("1")) {
                return true;
            }
            return false;
        }
    }
}
